package com.fudan.backend.service.impl;

import com.fudan.backend.dao.AccountDao;
import com.fudan.backend.dao.StoreDao;
import com.fudan.backend.dao.UserDao;
import com.fudan.backend.exception.BaseException;
import com.fudan.backend.exception.RetCode;
import com.fudan.backend.pojo.Account;
import com.fudan.backend.pojo.Store;
import com.fudan.backend.pojo.User;
import com.fudan.backend.pojo.statics.AccountStatic;
import com.fudan.backend.pojo.statics.BillType;
import com.fudan.backend.service.AccountService;
import com.fudan.backend.service.BillService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class AccountServiceImpl implements AccountService {
    @Autowired
    AccountDao accountDao;
    @Autowired
    StoreDao storeDao;
    @Autowired
    UserDao userDao;
    @Autowired
    BillService billService;
    @Override
    @Transactional
    public RetCode recharge(String accountId, Double amount) {
        if(amount < 0){
            return RetCode.ACCOUNT_RECHARGE_FAILURE;
        }
        int n = accountDao.addBalanceByAccountId(accountId, amount);
        billService.addBill(AccountStatic.RECHARGE_SRC_ACCOUNT_ID, accountId, amount, BillType.Account_RECHARGE, "外部充值");
        if(n == 0){
            return RetCode.ACCOUNT_RECHARGE_FAILURE;
        }
        return RetCode.ACCOUNT_SUCCESS;
    }

    @Override
    public Account getAccountByAccountId(String accountId) {
        Account account = accountDao.selectAccountByAccountId(accountId);
        if(account == null){
            throw new BaseException(RetCode.ACCOUNT_NOT_FOUND);
        }
        return account;
    }

    @Override
    public Account getAccountByUserId(String userId) {
        User user = userDao.selectUserByUserId(userId);
        if(user == null){
            throw new BaseException(RetCode.USER_ID_NOT_FOUND.getCode(), RetCode.USER_ID_NOT_FOUND.getMessage());
        }
        return accountDao.selectAccountByAccountId(user.getAccountId());
    }

    @Override
    public Account getAccountByStoreId(String storeId) {
        Store store = storeDao.selectStoreByStoreId(storeId);
        if(store == null){
            throw new BaseException(RetCode.STORE_NOT_FOUND.getCode(), RetCode.STORE_NOT_FOUND.getMessage());
        }
        return accountDao.selectAccountByAccountId(store.getAccountId());
    }

    @Override
    public List<Account> getAllStoreAccountByUserId(String userId) {
        List<Store> storeList = storeDao.selectStoreByUserId(userId);
         List<Account> list = new ArrayList<>();
        if(storeList.size() != 0){
            List<String> accountIdList = storeList.stream().map(Store::getAccountId).collect(Collectors.toList());
            list = accountDao.selectAccountListByAccountIdList(accountIdList);
        }
        return list;
    }

    @Override
    @Transactional
    public RetCode rechargeByUserId(String userId, Double amount) {
        User user = userDao.selectUserByUserId(userId);
        if(user == null){
            return RetCode.USER_ID_NOT_FOUND;
        }
        return this.recharge(user.getAccountId(), amount);
    }

    @Override
    @Transactional
    public RetCode rechargeByStoreId(String storeId, Double amount) {
        Store store = storeDao.selectStoreByStoreId(storeId);
        if(store == null){
            return RetCode.STORE_NOT_FOUND;
        }
        User user = userDao.selectUserByUserId(store.getUserId());
        this.transfer(user.getAccountId(), store.getAccountId(), amount, BillType.STORE_RECHARGE, "商店账户充值");
        return RetCode.ACCOUNT_SUCCESS;
    }

    @Override
    @Transactional
    public String transfer(String srcAccountId, String desAccountId, Double amount, Integer type) {
        return this.transfer(srcAccountId, desAccountId, amount, type, "");
    }

    @Override
    @Transactional
    public String transfer(String srcAccountId, String desAccountId, Double amount, Integer type, String moreInfo) {
        if(amount <= 0){
            throw new BaseException(RetCode.INVALID_REQUEST);
        }
        Account src = accountDao.selectAccountByAccountId(srcAccountId);
        Account des = accountDao.selectAccountByAccountId(desAccountId);
        if(src == null || des == null){
            throw new BaseException(RetCode.ACCOUNT_NOT_FOUND);
        }
        if(src.getBalance() - amount < 0){
            throw new BaseException(RetCode.ACCOUNT_INSUFFICIENT_BALANCE);
        }
        accountDao.addBalanceByAccountId(srcAccountId, -amount);
        accountDao.addBalanceByAccountId(desAccountId, amount);
        return billService.addBill(srcAccountId, desAccountId, amount, type, moreInfo);
    }
}
